import configparser

import datetime

import json

import sys

from PyQt5 import QtWidgets

from Ui_main_window import Ui_MainWindow

from tdr import CALLBACK_CMD, RECEIVE_ERROR, RECEIVE_SUCCES, STATUSBAR_MESSAGE
from tdr import ERRMSGSRC_LOGIN, ERRMSGSRC_MARKETSTATE, SH, SZ
from tdr import MARKET_STATE_BREAK, MARKET_STATE_CLOSE
from tdr import SUBSCRIBE_FAIL, SUBSCRIBE_SUCCESS

from twisted.internet import reactor

from twisted.internet.protocol import ClientFactory, Protocol

from twisted.python import log

RED = "color: rgb(255, 0, 0);"
GREEN = "color: rgb(0, 255, 0);"
WHITE = "color: rgb(255, 255, 255);"


class MarketDataSendProtocol(Protocol):
    def connectionMade(self):
        self.factory.clientReady(self)

    def connectionLost(self, reason):
        print(("已经与服务器 %s 断开连接，原因是：%s"
               "" % (self.transport.getPeer(), reason)))
        log.msg(("已经与服务器 %s 断开连接，原因是：%s"
                 "" % (self.transport.getPeer(), reason)))

    def send_data(self, data):
        self.transport.write(data)

    def dataReceived(self, data):
        # 收到数据推送
        print("收到服务器推送数据：%s" % data)
        log.msg("收到服务器推送数据：%s" % data)
        self.factory.callbackProcess(data)


class MarketClientFactory(ClientFactory):
    protocol = MarketDataSendProtocol
    # _signal = QtCore.pyqtSignal(dict)

    def __init__(self, connect_success_callback,
                 connect_fail_callback, recv_callback):
        # super(MarketClientFactory, self).__init__()
        log.msg("工厂正在初始化...")
        self.connect_success_callback = connect_success_callback
        self.connect_fail_callback = connect_fail_callback
        self.recv_callback = recv_callback
        self.client = None

    def subscribe_action(self, data):
        send_data = json.dumps(data).encode('utf-8')
        print("准备订阅请求给服务端：%s" % data)
        log.msg("准备订阅请求给服务端：%s" % data)
        self.client.send_data(send_data)

    def callbackProcess(self, data):
        log.msg("收到Protocol的回调数据，准备发送到窗体。")
        receive_data = json.loads(data)
        # self._signal.emit(receive_data)
        self.recv_callback(receive_data)
        log.msg("完成数据发送。")

    def clientConnectionFailed(self, connector, reason):
        self.connect_fail_callback(reason)

    def clientReady(self, client):
        self.client = client
        self.connect_success_callback()

    def send_data(self, data):
        if self.client:
            send_data = json.dumps(data).encode('utf-8')
            print("准备发送信息给服务端：%s" % data)
            log.msg("准备发送信息给服务端：%s" % data)
            self.client.send_data(send_data)


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):

    def __init__(self, reactor, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.lineEdit.returnPressed.connect(self.query_action)
        self.label_name.setText('名称')
        self.label_code.setText('代码')
        self.sCode = '510900'
        self.sMarket = 'SH'
        self.statusbar.showMessage("应用程序就绪")
        self.ask_price = [0 for i in range(10)]
        self.ask_vol = [0 for i in range(10)]
        self.bid_price = [0 for i in range(10)]
        self.bid_vol = [0 for i in range(10)]
        self.ask_price_last = [0 for i in range(10)]
        self.ask_vol_last = [0 for i in range(10)]
        self.bid_price_last = [0 for i in range(10)]
        self.bid_vol_last = [0 for i in range(10)]
        self.reactor = reactor
        cf = configparser.ConfigParser()
        cf.read("client_config.ini")
        # 正式服务器用配置
        # self.ini_section = "server"
        # 测试服务器用配置
        ini_section = cf.get("default", "default_section")
        server_ip = cf.get(ini_section, "ip")
        server_port = int(cf.get(ini_section, "port"))
        self.client = MarketClientFactory(self.on_client_connect_success,
                                          self.on_client_connect_fail,
                                          self.on_client_receive)
        # self.client._signal.connect(self.on_client_receive)
        self.connection = self.reactor.connectTCP(server_ip, server_port,
                                                  self.client)

    def on_client_connect_success(self):
        log.msg('成功连接服务器！')
        self.lineEdit.setText("60000")
        self.query_action()

    def on_client_connect_fail(self, reason):
        # reason is a twisted.python.failure.Failure  object
        log.msg('服务器连接失败！原因是: %s' % reason.getErrorMessage())

    def on_client_receive(self, dict_msg):
        if 'event_type' in dict_msg:
            log.msg('收到Factory回调数据：%s' % dict_msg)
            if dict_msg['event_type'] == RECEIVE_SUCCES:
                sCode = dict_msg['sCode']
                # 推送的行情是窗口当前订阅的代码
                if sCode == self.sCode:
                    self.label_code.setText(dict_msg['sCode'])
                    self.label_name.setText(dict_msg['sName'])
                    if sCode[0] in ['5', '1']:
                        uPreClose = str('%.3f' % (
                            dict_msg['uPreClose'] / 10000))
                    else:
                        uPreClose = str('%.2f' % (
                            dict_msg['uPreClose'] / 10000))
                    # log.msg("uPreClose=%s" % uPreClose)
                    log.msg("正在更新窗体...")
                    for i in range(10):
                        # ETF类别，保留三位小数
                        if sCode[0] == '5':
                            self.ask_price[i] = str('%.3f' % (
                                dict_msg['ask_price_%s' % i] / 10000))
                            self.bid_price[i] = str('%.3f' % (
                                dict_msg['bid_price_%s' % i] / 10000))
                            self.ask_vol[i] = dict_msg['ask_vol_%s' % i] // 100
                            self.bid_vol[i] = dict_msg['bid_vol_%s' % i] // 100
                        # 转债类别，保留三位小数
                        elif sCode[0] == '1':
                            self.ask_price[i] = str('%.3f' % (
                                dict_msg['ask_price_%s' % i] / 10000))
                            self.bid_price[i] = str('%.3f' % (
                                dict_msg['bid_price_%s' % i] / 10000))
                            self.ask_vol[i] = dict_msg['ask_vol_%s' % i]
                            self.bid_vol[i] = dict_msg['bid_vol_%s' % i]
                        # 证券价格，保留两位小数
                        else:
                            self.ask_price[i] = str('%.2f' % (
                                dict_msg['ask_price_%s' % i] / 10000))
                            self.bid_price[i] = str('%.2f' % (
                                dict_msg['bid_price_%s' % i] / 10000))
                            self.ask_vol[i] = dict_msg['ask_vol_%s' % i] // 100
                            self.bid_vol[i] = dict_msg['bid_vol_%s' % i] // 100

                        # 为内容填充数值
                        object_ask_label = self.findChild((QtWidgets.QLabel, ),
                                                          ('label_ask_price_%s'
                                                           '' % (i + 1)))
                        if object_ask_label:
                            object_ask_label.setText(self.ask_price[i])

                        object_ask_vol = self.findChild((QtWidgets.QLabel, ),
                                                        ('label_ask_vol_%s'
                                                         '' % (i + 1)))
                        if object_ask_vol:
                            object_ask_vol.setText(str(self.ask_vol[i]))
                        object_bid_label = self.findChild((QtWidgets.QLabel, ),
                                                          ('label_bid_price_%s'
                                                           '' % (i + 1)))
                        if object_bid_label:
                            object_bid_label.setText(self.bid_price[i])

                        object_bid_vol = self.findChild((QtWidgets.QLabel, ),
                                                        ('label_bid_vol_%s'
                                                         '' % (i + 1)))
                        if object_bid_vol:
                            object_bid_vol.setText(str(self.bid_vol[i]))

                        # 设置颜色
                        # log.msg(self.ask_price[i])
                        if self.ask_price[i] == uPreClose:
                            object_ask_label.setStyleSheet(WHITE)
                        elif float(self.ask_price[i]) < float(uPreClose):
                            object_ask_label.setStyleSheet(GREEN)
                        else:
                            object_ask_label.setStyleSheet(RED)

                        if self.bid_price[i] == uPreClose:
                            object_bid_label.setStyleSheet(WHITE)
                        elif float(self.bid_price[i]) < float(uPreClose):
                            object_bid_label.setStyleSheet(GREEN)
                        else:
                            object_bid_label.setStyleSheet(RED)

                        object_label = self.findChild((QtWidgets.QLabel, ),
                                                      ('label_ask_change_%s'
                                                       '' % (i + 1)))
                        if object_label:
                            object_label.setText("")
                            if self.ask_price[i] in self.ask_price_last:
                                vol_index = self.ask_price_last.index(self.ask_price[i])
                                vol_diff = self.ask_vol[i] - self.ask_vol_last[vol_index]
                                if abs(vol_diff) >= 1:
                                    if vol_diff > 0:
                                        object_label.setText('+%s' % str(vol_diff))
                                        object_label.setStyleSheet(RED)
                                    else:
                                        object_label.setText(str(vol_diff))
                                        object_label.setStyleSheet(GREEN)

                        object_label = self.findChild((QtWidgets.QLabel, ),
                                                      ('label_bid_change_%s'
                                                       '' % (i + 1)))
                        if object_label:
                            object_label.setText("")
                            if self.bid_price[i] in self.bid_price_last:
                                vol_index = self.bid_price_last.index(self.bid_price[i])
                                vol_diff = self.bid_vol[i] - self.bid_vol_last[vol_index]
                                if abs(vol_diff) >= 1:
                                    if vol_diff > 0:
                                        object_label.setText('+%s' % str(vol_diff))
                                        object_label.setStyleSheet(RED)
                                    else:
                                        object_label.setText(str(vol_diff))
                                        object_label.setStyleSheet(GREEN)
                    self.ask_price_last = self.ask_price[:]
                    self.ask_vol_last = self.ask_vol[:]
                    self.bid_price_last = self.bid_price[:]
                    self.bid_vol_last = self.bid_vol[:]
                    str_dt = datetime.datetime.now().strftime("%H:%M:%S")
                    self.statusbar.showMessage('%s 收到行情数据推送' % str_dt)

            elif dict_msg['event_type'] == RECEIVE_ERROR:
                # log.msg("收到 on_Error 推送：信息是 %s" % dict_msg)
                str_dt = datetime.datetime.now().strftime("%H:%M:%S")
                nError = dict_msg['nError']
                nErrSource = dict_msg['nErrSource']
                uData = dict_msg['uData']
                if (nErrSource == ERRMSGSRC_MARKETSTATE and
                   uData == MARKET_STATE_BREAK and
                   nError == SH):
                    log.msg('收到沪市休市信号。')
                    self.statusbar.showMessage('%s 收到沪市休市信号。' % str_dt)
                if (nErrSource == ERRMSGSRC_MARKETSTATE and
                   uData == MARKET_STATE_CLOSE and nError == SH):
                    log.msg('收到沪市闭市信号。')
                    self.statusbar.showMessage('%s 收到沪市闭市信号。' % str_dt)
                if (nErrSource == ERRMSGSRC_MARKETSTATE and
                   uData == MARKET_STATE_BREAK and nError == SZ):
                    log.msg('收到深市休市信号。')
                    self.statusbar.showMessage('%s 收到深市休市信号。' % str_dt)
                if (nErrSource == ERRMSGSRC_MARKETSTATE and
                   uData == MARKET_STATE_CLOSE and nError == SZ):
                    log.msg('收到深市闭市信号。')
                    self.statusbar.showMessage('%s 收到深市闭市信号。' % str_dt)
                if nErrSource == ERRMSGSRC_LOGIN:
                    log.msg('收到行情服务器停止信号。')
                    self.statusbar.showMessage('%s 收到行情服务器停止信号。' % str_dt)

            elif dict_msg['event_type'] == SUBSCRIBE_SUCCESS:
                self.sCode = dict_msg['sCode']
                self.sMarket = dict_msg['sMarket']
                message = ('证券代码 %s.%s 订阅成功！当前证券显示代码已切换。'
                           '' % (self.sCode, self.sMarket))
                log.msg(message)
                self.statusbar.showMessage(message)
                str_dt = datetime.datetime.now().strftime("%H:%M:%S")
                self.statusbar.showMessage('%s 行情订阅成功！' % str_dt)

            elif dict_msg['event_type'] == SUBSCRIBE_FAIL:
                message = '证券代码 %s 订阅失败！当前证券显示代码为 %s.%s' % (
                    dict_msg['sCode'], self.sCode, self.sMarket)
                log.msg(message)
                self.statusbar.showMessage(message)
                str_dt = datetime.datetime.now().strftime("%H:%M:%S")
                self.statusbar.showMessage('%s 行情订阅失败！' % str_dt)

            elif dict_msg['event_type'] == STATUSBAR_MESSAGE:
                message = dict_msg['message']
                self.statusbar.showMessage(message)

    def closeEvent(self, e):
        # pass
        self.reactor.stop()

    def log_file(self, log_str):
        str_dt = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        str_dt2 = datetime.datetime.now().strftime("%Y-%m-%d")
        log_filename = '%s.log' % str_dt2
        with open(log_filename, 'a', encoding='utf-8') as my_logfile:
            log_str = '%s %s' % (str_dt, log_str)
            my_logfile.write(log_str + '\n')

    def query_action(self):
        user_input = self.lineEdit.text().lower()
        self.lineEdit.setText("")
        dict_msg = {}
        dict_msg['event_type'] = CALLBACK_CMD
        dict_msg['sCode'] = user_input
        self.client.subscribe_action(dict_msg)

    def clear_volchange_labels(self):
        for i in range(10):
            object_label = self.findChild((QtWidgets.QLabel, ),
                                          'label_ask_change_%s' % (i + 1))
            if object_label:
                object_label.setText("")
            object_label = self.findChild((QtWidgets.QLabel, ),
                                          'label_bid_change_%s' % (i + 1))
            if object_label:
                object_label.setText("")


if __name__ == '__main__':
    now = datetime.datetime.now().strftime('%Y-%m-%d')
    log.startLogging(open("client_%s.log" % now, 'w'))
    log.msg('=====================程序开始运行！=====================')
    APP = QtWidgets.QApplication(sys.argv)
    UI = MainWindow(reactor)
    UI.show()
    # APP.exec_()
    import time
    time.sleep(2000)
    # reactor.run()
